/**
 * @projectDescription JavaScript for xhtmlgateway.xml
 * @link http://code.google.com/p/wikignpi
 * @author Bruno Santos
 * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
 *
 * Usage:
 *   Shown here: http://code.google.com/p/wikignpi/wiki/GadgetThatXHTML
 */

var my_log = function(text){};
if(window.console && window.console.log){
   my_log = window.console.log;
}

// Get userprefs
var prefs = new gadgets.Prefs();

gnpi_projectname = prefs.getString("projectname");
gnpi_subversion = prefs.getString("subversion");
gnpi_xhtmlURL = prefs.getString("xhtmlURL");
gnpi_baseURL = prefs.getString("baseURL");
gnpi_autoresize = prefs.getBool("autoresize");
gnpi_disableWarnings = prefs.getBool("disableWarnings");
gnpi_openURLSInNewWindow = prefs.getBool("openURLSInNewWindow");
gnpi_showURLAsTitle = prefs.getBool("showURL");
gnpi_refreshRate = prefs.getInt("cachedTime");
gnpi_disableScripts = prefs.getBool("disableScripts");
gnpi_plugins = prefs.getString("plugins");

gnpi_monitor_height = -1;
gnpi_pre_plugins = {};
gnpi_post_plugins = {};
gnpi_count_injected_plugins = 0;

//setup the base location
gnpi_baselocation="http://";
if(gnpi_subversion.indexOf("hg")>=0) {
  gnpi_baselocation += "wiki." + gnpi_projectname + ".googlecode.com";
} else { /* gnpi_subversion.indexOf("svn")>=0 */
  gnpi_baselocation += gnpi_projectname + ".googlecode.com";
}

gnpi_xhtmlURLfull = parseUrl(gnpi_xhtmlURL);
if(gnpi_baseURL.length == 0) {gnpi_baseURL = gnpi_xhtmlURLfull.protocol + '://' + gnpi_xhtmlURLfull.host + gnpi_xhtmlURLfull.path;}

//nuke right off the bat the hash
window.location.hash='';

/* ------------------------------------------------------------------------ */
/*                               Functions                                  */

//source: http://lawrence.ecorp.net/inet/samples/regexp-parse.php
function parseUrl(data) {
    var e=/((http|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+\.[^#?\s]+)(#[\w\-]+)?/;

    if (data.match(e)) {
        return  {url: RegExp['$&'],
                protocol: RegExp.$2,
                host:RegExp.$3,
                path:RegExp.$4,
                file:RegExp.$6,
                hash:RegExp.$7};
    } else {
        return  {url:"", protocol:"",host:"",path:"",file:"",hash:""};
    }
};

function makeCachedRequest(url, callback, params, refreshInterval) {
  var ts = new Date().getTime();
  var sep = "?";
  if (refreshInterval && refreshInterval > 0) {
    ts = Math.floor(ts / (refreshInterval * 1000));
  }
  if (url.indexOf("?") > -1) {
    sep = "&";
  }
  url = [ url, sep, "nocache=", ts ].join("");
  gadgets.io.makeRequest(url, callback, params);
};

function getHTML() {
  var params = {};

  params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;
  if(gnpi_refreshRate>-1) {
    makeCachedRequest(gnpi_xhtmlURL, posthtml, params, gnpi_refreshRate);
  } else {
    gadgets.io.makeRequest(gnpi_xhtmlURL, posthtml, params);
  }
};

function posthtml(data)
{
  $('body').attr('dir',null);
  $('#htmlcontent').append('<p>0&#37;</p>');
  if(data.errors.length == 0) {
    domdata = GNPI_runPrePlugins(data.data);

    $('#htmlcontent').append('<p>10&#37;</p>');

    //0 - Inject <base>
    $('head').append('<base href="' + gnpi_baseURL + '"/>');

    $('#htmlcontent').append('<p>20&#37;</p>');

    //1st - Get, strip and inject <link> stuff into <head>
    processCSSLinks(domdata);

    $('#htmlcontent').append('<p>50&#37;</p>');

    //2nd - Get, strip <script> stuff and inject <script> stuff into <head>
    var scriptList = processScripts(domdata);

    $('#htmlcontent').append('<p>80&#37;</p>');

    //3rd - inject the remainder content into the target div "htmlcontent"
    $('#htmlcontent')[0].innerHTML = processBody(domdata);

    if(gnpi_showURLAsTitle){ $('#htmlcontent').prepend("<strong>URL: "+gnpi_xhtmlURL+"</strong>");}

    GNPI_runPostPlugins($('#htmlcontent'));

    //4th - Inject <script> stuff back into <head>
    if(!gnpi_disableScripts) {
      reinjectScripts(scriptList);
    }

    //5th - Jump to the hash
    setTimeout(jumpToHash,1000);

    //finally, resize the iframe it's in...
    if(gnpi_autoresize) $(resizeMonitor);
  } else {
    $('#htmlcontent')[0].innerHTML="Failed... Errors found:<br><p>"+data.errors.join('<br>')+"</p>";
  }
};

function processCSSLinks(domdata) {
  var csslinks = domdata.getElementsByTagName("link");

  //Have to search backwards, because the object is moved directly to the real document!
  for(var csslink = csslinks.length-1; csslink >=0 ; csslink--) {
    var cl = csslinks.item(csslink);
    var h = cl.getAttribute("href");
    if(h.indexOf('http') != 0) {
      h = gnpi_baseURL + h;
      cl.setAttribute("href",h);
    }
    $('head').append(cl);
  }
};

function processScripts(domdata) {
  var scriptListA = domdata.getElementsByTagName("script");
  var scriptListB = scriptListA;

  //First make a deep copy of all scripts...
  for(var slink = 0; slink < scriptListA.length; slink++) {
    scriptListB[slink] = jQuery.extend(true, new Object(), scriptListA[slink]);
    var s = scriptListB[slink].getAttribute("src");
    if(s.indexOf('http') != 0) {
      s = gnpi_baseURL + s;
      scriptListB[slink].setAttribute("src",s);
    }
  }

  //Now remove those scripts
  $(domdata).remove('script');

  return scriptListB;
};

function jumpHere(a) {
  window.location.hash=''; //remove the hash, since it could damage the jump
  var ma = window.location.href.match(/(up_xhtmlURL=)([^&]*)(&+)/);
  var nu = window.location.href.replace(ma[0], ma[1] + encodeURIComponent(a.href) + ma[3]);
  window.location.href = nu;
  return false;
};

function jumpToThisHash(a) {
  var hashstr="";
  var pos = a.href.indexOf("#");
  if(pos>=0) hashstr = a.href.substr(pos);
  window.location.hash=hashstr;
  pos = $("a[name="+window.location.hash.substr(1)+"]").position();
  if (pos == null) pos = $("a[id="+window.location.hash.substr(1)+"]").position();
  if (pos != null) window.scrollTo(pos.left, pos.top);
  return false;
};

function fixHREF(a) {
  var href = a.getAttribute('href');
  if(href == null) return;
  if(href.indexOf(gnpi_baseURL) == 0 || href.indexOf('http') != 0) {
    //inside jump...
    if(href.indexOf('#') == 0) {
      href = gnpi_xhtmlURLfull.file + href;
      a.setAttribute("href",href);
      a.setAttribute("onclick", "return jumpToThisHash(this);");
      return; //all done here
    }

    if(href.indexOf(gnpi_xhtmlURLfull.file) == 0) {
      //leave only the hash
      href = href.replace(gnpi_xhtmlURLfull.file,'');
      if(href.length == 0) href = '#';
    } else {
      if(href.indexOf('http') != 0) href = gnpi_baseURL + href;
      a.setAttribute("onclick", "return jumpHere(this);");
    }
    if(href.indexOf('#') == 0) {
      href = gnpi_xhtmlURLfull.file + href;
      a.setAttribute("onclick", "return jumpToThisHash(this);");
    }
    a.setAttribute("href",href);
  } else {
    //jump outside
    a.setAttribute("target","_blank");
  }
};

function fixURL(urlorig) {
  var urlline = urlorig;
  if(urlline.indexOf('http') != 0 && urlline.indexOf('/') != 0) {
    urlline = gnpi_baseURL + urlline;
  }
  else if(urlline.indexOf('/') == 0)
  {
    urlline = gnpi_xhtmlURLfull.protocol + '://' + gnpi_xhtmlURLfull.host + urlline;
  }

  return urlline;
};

function processBody(domdata) {
  var dbody = domdata.getElementsByTagName("body").item(0);
  var html='';

  //process hyperlinks - NOTE: links that don't start with the same base, should jump to a new window/tab!
  var list = dbody.getElementsByTagName('a');
  for(var i=0; i < list.length; i++) {
    var a = list.item(i);
    fixHREF(a);
  }

  //process images
  list = dbody.getElementsByTagName('img');
  for(var i=0; i < list.length; i++) {
    var img = list.item(i);
    img.getAttribute("src",fixURL(img.getAttribute("src")));
  }

  //process areas in images
  list = dbody.getElementsByTagName('area');
  for(var i=0; i < list.length; i++) {
    var area = list.item(i);
    fixHREF(area);
  }

  //process embed (flash and all)
  list = dbody.getElementsByTagName('embed');
  for(var i=0; i < list.length; i++) {
    var emb = list.item(i);
    emb.getAttribute("src",fixURL(emb.getAttribute("src")));
  }

  //process iframes... take into account corner case that uses "//" instead of "http://"
  list = dbody.getElementsByTagName('iframe');
  for(var i=0; i < list.length; i++) {
    var iframe = list.item(i);
    iframe.getAttribute("src",fixURL(iframe.getAttribute("src")));
  }

  html = dbody.innerHTML;
  return html;
};

function reinjectScripts(scriptList) {
  for(var slink = 0; slink < scriptList.length; slink++) {
    $('head').append(scriptList.item(slink));
  }
};

function jumpToHash(){
  var hashToJ2 = gnpi_xhtmlURLfull.hash != null && gnpi_xhtmlURLfull.hash.length > 0;
  if(hashToJ2) {
    if($(gnpi_xhtmlURLfull.hash).length>0 && (window.location.hash == null || window.location.hash.length <= 1)) {
      var pos = $("a[name="+gnpi_xhtmlURLfull.hash.substr(1)+"]").position();
      if (pos == null) pos = $("id[name="+gnpi_xhtmlURLfull.hash.substr(1)+"]").position();
      if (pos != null) window.scrollTo(pos.left, pos.top);
      window.location.hash=gnpi_xhtmlURLfull.hash;
    }else{
      setTimeout(jumpToHash,1000);
    }
  }
};

function resizeMonitor()
{
  var outerH = $('body').outerHeight( true );
  if (outerH != gnpi_monitor_height) {
    gnpi_monitor_height = outerH;
    gadgets.window.adjustHeight();
  }
  setTimeout(resizeMonitor,1000);
};

/* This function is called by the plug-in itself! */
function GNPI_registerPrePlugin(plugin_name, plugin_function)
{
  gnpi_pre_plugins[plugin_name] = plugin_function;
  my_log(gnpi_pre_plugins);
};

/* This function is called by the plug-in itself! */
function GNPI_registerPostPlugin(plugin_name, plugin_function)
{
  gnpi_post_plugins[plugin_name] = plugin_function;
};

/* NOTE: plugin_options is already an array with unparsed options */
function processPluginOptions(plugin_name, plugin_options)
{
    for(var j=0; j<plugin_options.length; j++)
    {
      if(plugin_options[j].length>0)
      {
        eval('___' + plugin_name + '_' + unescape(plugin_options[j]) + ';');
      }
    }
};

function generateGNPIPluginURL(plugin_name)
{
  var url="";
  if(gnpi_subversion.indexOf("hg")>=0) {
    url += gnpi_baselocation + "/hg/gadgets/htmlplugins/";
  } else { /* gnpi_subversion.indexOf("svn")>=0 */
    url += gnpi_baselocation + "/svn/wiki/gadgets/htmlplugins/";
  }
  url += plugin_name + ".js";
  return url;
};

function injectPluginScriptIntoHead(plugin_url)
{
  var script=window.document.createElement('script');
  script.src=plugin_url;
  var head=window.document.getElementsByTagName('head')[0],
  done=false;
  // Attach handlers for all browsers
  script.onload=script.onreadystatechange = function(){
    if ( !done && (!this.readyState
        || this.readyState == 'loaded'
        || this.readyState == 'complete') ) {
        done=true;
        script.onload = script.onreadystatechange = null;
        head.removeChild(script);
    }
  };
  head.appendChild(script);
};

function loadGNPIPlugins()
{
  gnpi_plugins = unescape(gnpi_plugins);
  var j, plugin_list = gnpi_plugins.split('|');

  for(j in plugin_list) {
    if(plugin_list[j].length>0) {
      var plugin_info = plugin_list[j].split('?');
      var plugin_name = plugin_info[0];
      if(plugin_info.length>1) {
        processPluginOptions(plugin_name, plugin_info[1].split('&'));
      }
      injectPluginScriptIntoHead(generateGNPIPluginURL(plugin_name));
      gnpi_count_injected_plugins++;
    }
  }
};


function GNPI_runPrePlugins(domdata)
{
  var j;
  for(j in gnpi_pre_plugins) {
    domdata = gnpi_pre_plugins[j](domdata);
  }
  return domdata;
};

function GNPI_runPostPlugins(jQhtmlcontent)
{
  var j;
  for(j in gnpi_post_plugins) {
    gnpi_post_plugins[j](jQhtmlcontent);
  }
};

/*                        End of Functions                                  */
/* ------------------------------------------------------------------------ */

loadGNPIPlugins();

gadgets.util.registerOnLoadHandler(getHTML);
